# coding:utf8
from django.http import JsonResponse
from django.shortcuts import render, redirect
from django.urls import reverse
from django.views import View
from django.views.generic.base import View as base_view
from django.contrib.auth.hashers import check_password
from django.core.cache import cache
from .models import User
# from MyQR import myqr
import hashlib
import time
from functools import wraps
from log.logger import logger


# 可优化的地方：
# 1.注册中增加手机号码有效性的校验，防止恶意注册 √  用户名校验
# 2.分页，优化性能 √
# 3.删除多余的账号字段，使用手机号和用户名即可 √
# 4.增加自动回复短语匹配库 √
# 5.位置更新功能转移到中间件中实现，只要发生请求就立即更新实时位置，无需额外调用接口 √
# 6.使用websocket做实时聊天


# 记录开发中出现的问题，以及解决的方案

# 登录验证
def auth(require_admin=False):
    def outer(func):

        @wraps(func)
        def inner(*args, **kwargs):

            # 根据第一个参数是否是视图函数的实例来取self和request的值
            view_flag = 0
            if isinstance(args[0], base_view):
                self = args[0]
                request = args[1]
                view_flag = 1
            else:
                request = args[0]

            # 前端登录状态失效
            try:
                username = request.COOKIES.get('username')
                status_key = request.COOKIES.get(username)

            except KeyError as e:
                return JsonResponse({'code': '400', 'msg': 'cookie登录过时,请重新登录!'})

            # 后端登录状态失效
            loc_status_key = cache.get(username)

            if not loc_status_key or status_key != loc_status_key:
                return JsonResponse({'code': '400', 'msg': 'session登录过时,请重新登录!'})

            user = User.get_user_by_username(username)

            # 管理员身份要求
            if require_admin and not user.is_staff:
                return JsonResponse({'code': '400', 'msg': '抱歉,您没有权限!'})

            # 获取user后绑定在request上
            args[view_flag].user = user

            # try:
            #     res = func(*args, **kwargs)
            # except Exception as e:
            #     logger.error(
            # f'{request.user}[{request.META.get("REMOTE_ADDR")}];{request.path}[{request.method}];error:{e}.')
            #     return JsonResponse({'code': '500', 'msg': '抱歉,服务器异常!'})
            res = func(*args, **kwargs)

            return res

        return inner

    return outer


# 注册
class RegisterView(View):

    def post(self, request):

        # 获取参数
        mobile = request.POST.get('mobile')

        # 如果手机号码不合法直接返回
        if not User.is_valid_mobile(mobile):
            return JsonResponse(
                {
                    'code': '400',
                    'msg': '手机号无效！'
                }
            )

        # 如果已经注册就直接返回
        if User.is_exists_mobile(mobile):
            return JsonResponse(
                {
                    'code': '400',
                    'msg': '该手机号已注册!'
                }
            )

        password = request.POST.get('password')
        longitude = request.POST.get('longitude', 0)
        latitude = request.POST.get('latitude', 0)

        # 进行注册
        User.create_user(mobile, password, longitude, latitude)

        return JsonResponse(
            {'code': '200',
             'msg': '注册成功！'
             })


# 登录
class LoginView(View):

    def get(self, request):
        return render(request, 'user/login.html')

    def post(self, request):

        # 获取参数
        username = request.POST.get('username')
        password = request.POST.get('password')

        # 检测用户名是否存在
        tmp_user = User.get_by_username(username)

        # 用户名/手机号不存在
        if not tmp_user:
            return JsonResponse({
                'code': '400',
                'msg': '账号或手机号不存在!'
            })

        # 密码不正确
        if not check_password(password, tmp_user.password):
            return JsonResponse({
                'code': '400',
                'msg': '密码不正确!'
            })

        http_res = JsonResponse({
            'code': '200',
            'msg': '登录成功!'
        })

        #重定向到聊天界面
        # http_res = redirect(reverse('chat:index'))

        # 生成状态码
        key = str(tmp_user.username) + str(time.time())
        status_key = hashlib.sha256(bytes(key, encoding='utf8')).hexdigest()

        # 生成二维码 TODO 扫码登录
        # myqr.run(words=status_key,save_dir='',save_name=f'{status_key}.jpg')

        # 前端写入cookie
        http_res.set_cookie(
            'username', tmp_user.username, max_age=7 * 24 * 60 * 60)
        http_res.set_cookie(
            tmp_user.username, status_key, max_age=7 * 24 * 60 * 60)

        # 后端写入缓存
        cache.set(tmp_user.username, status_key, 7 * 24 * 60 * 60)

        return http_res


# 登出
class LogoutView(View):

    def post(self, request):
        username = request.COOKIES.get('username')
        http_res = JsonResponse({
            'code': '200',
            'msg': '登出成功!'
        })

        # 删除cookie
        http_res.delete_cookie('username')
        http_res.delete_cookie(username)

        # 删除缓存
        cache.delete(username)

        return http_res


# 获取在线用户
@auth()
def get_online_users(request):
    if request.method == 'GET':
        page = int(request.GET.get('page', '1'))
        size = int(request.GET.get('size', '10'))
        online_users = User.get_online_users(page, size)
        return JsonResponse(
            {'code': '200',
             'msg': '响应成功!',
             'data': list(online_users)
             }
        )


# 获取可用的客服
@auth()
def get_available_staff(request):
    if request.method == 'GET':
        available_staff = User.get_available_staff()

        return JsonResponse(
            {'code': '200',
             'msg': '响应成功!',
             'data': available_staff
             }
        )


# 获取临近用户
@auth()
def get_nearby_users(request):
    if request.method == 'GET':
        distance = int(request.GET.get('distance', '10'))  # 距离
        page = int(request.GET.get('page', '1'))
        size = int(request.GET.get('size', '10'))

        # 获取附近的用户
        nearby_users = request.user.get_nearby_users(distance, page, size)

        return JsonResponse({
            'code': '200',
            'msg': '响应成功!',
            'data': nearby_users
        })
